#include "acl_stdafx.hpp"
#ifndef ACL_PREPARE_COMPILE
#include "stdlib/log.hpp"
#include "stdlib/util.hpp"
#include "stdlib/string.hpp"
#include "stream/socket_stream.hpp"
#include "master/master_udp.hpp"
#endif

namespace acl
{

master_udp::master_udp(void) {}

master_udp::~master_udp(void)
{
	for (std::vector<socket_stream*>::iterator it = sstreams_.begin();
		it != sstreams_.end(); ++it)
	{
		(*it)->unbind();
		delete *it;
	}
}

static bool __has_called = false;

void master_udp::run(int argc, char** argv)
{
	// 调用 acl 服务器框架中 UDP 服务器模板接口
	acl_udp_server_main(argc, argv, service_main,
		ACL_MASTER_SERVER_CTX, this,
		ACL_APP_CTL_THREAD_INIT_CTX, this,
		ACL_MASTER_SERVER_ON_BIND, service_on_bind,
		ACL_MASTER_SERVER_PRE_INIT, service_pre_jail,
		ACL_MASTER_SERVER_POST_INIT, service_init,
		ACL_MASTER_SERVER_EXIT, service_exit,
		ACL_MASTER_SERVER_THREAD_INIT, thread_init,
		ACL_MASTER_SERVER_SIGHUP, service_on_sighup,
		ACL_MASTER_SERVER_INT_TABLE, conf_.get_int_cfg(),
		ACL_MASTER_SERVER_STR_TABLE, conf_.get_str_cfg(),
		ACL_MASTER_SERVER_BOOL_TABLE, conf_.get_bool_cfg(),
		ACL_MASTER_SERVER_INT64_TABLE, conf_.get_int64_cfg(),
		0);
}

void master_udp::run_daemon(int argc, char** argv)
{
#ifdef ACL_WINDOWS
	logger_fatal("no support win32 yet!");
#else
	// 每个进程只能有一个实例在运行
	acl_assert(__has_called == false);
	__has_called = true;
	daemon_mode_ = true;

	run(argc, argv);
#endif
}

const char* master_udp::get_conf_path(void) const
{
#ifndef ACL_WINDOWS
	if (daemon_mode_)
	{
		const char* ptr = acl_udp_server_conf();
		return ptr && *ptr ? ptr : NULL;
	}
	else
#endif
		return conf_.get_path();
}

//////////////////////////////////////////////////////////////////////////

bool master_udp::run_alone(const char* addrs, const char* path /* = NULL */,
	unsigned int)
{
#ifdef ACL_WINDOWS
	acl_cpp_init();
#endif

	// 每个进程只能有一个实例在运行
	acl_assert(__has_called == false);
	__has_called = true;
	daemon_mode_ = false;
	acl_assert(addrs && *addrs);

	int  argc = 0;
	const char *argv[6];

	const char* proc = acl_process_path();
	argv[argc++] = proc ? proc : "demo";
	argv[argc++] = "-n";
	argv[argc++] = addrs;
	if (path && *path)
	{
		argv[argc++] = "-f";
		argv[argc++] = path;
	}
	argv[argc++] = "-r";

	run(argc, (char**) argv);
	return true;
}

//////////////////////////////////////////////////////////////////////////

void master_udp::service_main(void* ctx, ACL_VSTREAM *stream)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu != NULL);

	socket_stream* ss = (socket_stream*) stream->context;
	acl_assert(ss);

/*
#ifndef	ACL_WINDOWS
	if (mu->daemon_mode_)
		acl_watchdog_pat();  // 必须通知 acl_master 框架一下
#endif
*/
	mu->on_read(ss);
}

void master_udp::service_pre_jail(void* ctx)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu != NULL);

#ifndef ACL_WINDOWS
	ACL_EVENT* eventp = acl_udp_server_event();
	mu->set_event(eventp);
#endif

	mu->proc_pre_jail();
}

void master_udp::service_init(void* ctx)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu != NULL);

	mu->proc_inited_ = true;
	mu->proc_on_init();
}

void master_udp::service_exit(void* ctx)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu != NULL);
	mu->proc_on_exit();
}

void master_udp::thread_init(void* ctx)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu != NULL);
	mu->thread_on_init();
}

void master_udp::service_on_bind(void* ctx, ACL_VSTREAM* stream)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu);

	socket_stream* ss = NEW socket_stream();
	if (ss->open(stream) == false)
		logger_fatal("open stream error!");
	stream->context = ss;
	mu->sstreams_.push_back(ss);

	mu->proc_on_bind(*ss);
}

int master_udp::service_on_sighup(void* ctx, ACL_VSTRING* buf)
{
	master_udp* mu = (master_udp *) ctx;
	acl_assert(mu);
	string s;
	bool ret = mu->proc_on_sighup(s);
	if (buf)
		acl_vstring_strcpy(buf, s.c_str());
	return ret ? 0 : -1;
}

}  // namespace acl
